/**
 * SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
 * SPDX-License-Identifier: Mulan PSL v2
 */
/* eslint-disable */

interface ThrottleOption {
    leading?: boolean
    trailing?: boolean
}

/**
 * 节流函数-频率控制 用于将高频率连续调用某函数控制为低频率
 * 抄 underscore.js 的，具体用法请看 _.throttle
 */
var throttle = function<T extends AnyFunction = AnyFunction>(func: T, wait: number, options?: ThrottleOption) {
    let context: SafeAny, args: IArguments, result: ReturnType<T> | undefined;
    var timeout: number | null = null;
    let previous: number = 0;
    options = options || {};
    var later = function() {
        previous = options!.leading === false ? 0 : new Date().getTime();
        timeout = null;
        result = func.apply(context, [].slice.call(args));
    };
    return function(this: SafeAny) {
        var now = new Date();
        if (!previous && options!.leading === false) {
            previous = now.getTime();
        }
        var remaining = wait - (now.getTime() - previous);
        context = this;
        args = arguments;
        if (remaining <= 0) {
            timeout && window.clearTimeout(timeout);
            timeout = null;
            previous = now.getTime();
            result = func.apply(context, [].slice.call(args));
        } else if (!timeout && options!.trailing !== false) {
            timeout = window.setTimeout(later, remaining);
        }
        return result;
    };
};

/**
 * 防抖函数-空闲控制 当高频率连续调用某函数停下来时，才会真正地去执行它
 * 抄 underscore.js 的，具体用法请看 _.debounce
 */
var debounce = function<T extends AnyFunction = AnyFunction>(func: T, wait: number, immediate?:boolean) {
    var timeout: number | null, args: IArguments, context: SafeAny, timestamp: number, result: ReturnType<T> | undefined;
    return function(this: SafeAny) {
        context = this;
        args = arguments;
        timestamp = new Date().getTime();
        var later = function() {
            var last = (new Date().getTime()) - timestamp;
            if (last < wait) {
                timeout = window.setTimeout(later, wait - last);
            } else {
                timeout = null;
                if (!immediate) {
                    result = func.apply(context, [].slice.call(args));
                }
            }
        };
        var callNow = immediate && !timeout;
        if (!timeout) {
            timeout = window.setTimeout(later, wait);
        }
        if (callNow) {
            result = func.apply(context, [].slice.call(args));
        }
        return result;
    };
};

export {
    throttle,
    debounce
};
